﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;

namespace InternetSpiderLib
{
    /// <summary>
    /// 场景过滤器
    /// </summary>
    public interface ISceneFilter
    {
        /// <summary>
        /// 场景过滤器
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        bool Filter(DataBox data);
    }

    /// <summary>
    /// 正则场景过滤器
    /// </summary>
    public class RegexSceneFilter : ISceneFilter
    {
        private Regex Regex = null;
        private string Key = null;

        public RegexSceneFilter(string key, Regex regex)
        {
            Key = key;
            Regex = regex;
        }

        public bool Filter(DataBox data)
        {
            if (string.IsNullOrEmpty(Key) || Regex == null)
                return false;

            string value = data.Get<string>(Key);
            return Regex.Match(value).Success;
        }
    }

    /// <summary>
    /// 内容包含过滤器
    /// （传递过来的数据中包含此数据则认为正常）
    /// </summary>
    public class ContainsSceneFilter : ISceneFilter
    {
        private KeyValuePair<string, Type> Key2Type = new KeyValuePair<string, Type>();

        public ContainsSceneFilter(string key, Type type)
        {
            Key2Type = new KeyValuePair<string, Type>(key, type);
        }

        public bool Filter(DataBox data)
        {
            if (string.IsNullOrEmpty(Key2Type.Key) || Key2Type.Value == null)
                return false;

            return data.Get(Key2Type.Key, Key2Type.Value) != null;
        }
    }

    /// <summary>
    /// 对比过滤器
    /// </summary>
    public class ContrastSceneFilter<T> : ISceneFilter
    {
        public string Key { get; set; }

        public T Value { get; set; }

        public ContrastSceneFilter(string key, T value)
        {
            Key = key;
            Value = value;
        }

        public bool Filter(DataBox data)
        {
            return data.Get<T>(Key).Equals(Value);
        }
    }

    /// <summary>
    /// 字符串内容包含过滤器
    /// </summary>
    public class StringContainsSceneFilter : ISceneFilter
    {
        private KeyValuePair<string, string> Key2Substring = new KeyValuePair<string, string>();

        public StringContainsSceneFilter(string key, string substring)
        {
            Key2Substring = new KeyValuePair<string, string>(key, substring);
        }

        public bool Filter(DataBox data)
        {
            if (string.IsNullOrEmpty(Key2Substring.Key) || string.IsNullOrEmpty(Key2Substring.Value))
                return false;

            var value = data.Get<string>(Key2Substring.Key);
            if (string.IsNullOrEmpty(value))
                return false;

            return value.Contains(Key2Substring.Value);
        }
    }

    /// <summary>
    /// 匿名的过滤器
    /// </summary>
    public class AnonymousSceneFilter : ISceneFilter
    {
        protected Func<DataBox, bool> Func { get; set; }

        public AnonymousSceneFilter(Func<DataBox, bool> func)
        {
            Func = func;
        }

        public bool Filter(DataBox data)
        {
            return Func?.Invoke(data) ?? false;
        }
    }

    /// <summary>
    /// 列表过滤器
    /// </summary>
    public class ListSceneFilter : ISceneFilter
    {
        protected virtual List<ISceneFilter> ChildFilter { get; set; } = new List<ISceneFilter>();

        public virtual bool Filter(DataBox data)
        {
            throw new NotImplementedException();
        }
    }

    /// <summary>
    /// 选择过滤器
    /// </summary>
    public class SelectSceneFilter : ListSceneFilter
    {
        public SelectSceneFilter(List<ISceneFilter> filters)
        {
            ChildFilter.AddRange(filters);
        }

        public override bool Filter(DataBox data)
        {
            foreach (var item in ChildFilter)
            {
                if (item.Filter(data))
                    return true;
            }

            return false;
        }
    }

    /// <summary>
    /// 顺序过滤器
    /// </summary>
    public class SequenceSceneFilter : ListSceneFilter
    {
        public SequenceSceneFilter(List<ISceneFilter> filters)
        {
            ChildFilter.AddRange(filters);
        }

        public override bool Filter(DataBox data)
        {
            foreach (var item in ChildFilter)
            {
                if (!item.Filter(data))
                    return false;
            }

            return true;
        }
    }
}
